<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>/home/zjh/git/Koala-UI/KoalaUI/WebContent/lib/Koala_Calendar.js</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.9.1/build/cssgrids/cssgrids-min.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
    <script src="http://yui.yahooapis.com/combo?3.9.1/build/yui/yui-min.js"></script>
</head>
<body class="yui3-skin-sam">

<div id="doc">
    <div id="hd" class="yui3-g header">
        <div class="yui3-u-3-4">
            
                <h1><img src="../assets/css/logo.png" title=""></h1>
            
        </div>
        <div class="yui3-u-1-4 version">
            <em>API Docs for: </em>
        </div>
    </div>
    <div id="bd" class="yui3-g">

        <div class="yui3-u-1-4">
            <div id="docs-sidebar" class="sidebar apidocs">
                <div id="api-list">
    <h2 class="off-left">APIs</h2>
    <div id="api-tabview" class="tabview">
        <ul class="tabs">
            <li><a href="#api-classes">Classes</a></li>
            <li><a href="#api-modules">Modules</a></li>
        </ul>

        <div id="api-tabview-filter">
            <input type="search" id="api-filter" placeholder="Type to filter APIs">
        </div>

        <div id="api-tabview-panel">
            <ul id="api-classes" class="apis classes">
            
                <li><a href="../classes/Accordion.html">Accordion</a></li>
            
                <li><a href="../classes/AutoComplete.html">AutoComplete</a></li>
            
                <li><a href="../classes/Button.html">Button</a></li>
            
                <li><a href="../classes/Carousel.html">Carousel</a></li>
            
                <li><a href="../classes/ColorPicker.html">ColorPicker</a></li>
            
                <li><a href="../classes/Combobox.html">Combobox</a></li>
            
                <li><a href="../classes/DateTimePicker.html">DateTimePicker</a></li>
            
                <li><a href="../classes/Grid.html">Grid</a></li>
            
                <li><a href="../classes/ListView.html">ListView</a></li>
            
                <li><a href="../classes/Popover.html">Popover</a></li>
            
                <li><a href="../classes/ProgressBar.html">ProgressBar</a></li>
            
                <li><a href="../classes/RichTextEditor.html">RichTextEditor</a></li>
            
                <li><a href="../classes/ScrollSpy.html">ScrollSpy</a></li>
            
                <li><a href="../classes/Select.html">Select</a></li>
            
                <li><a href="../classes/SideBar.html">SideBar</a></li>
            
                <li><a href="../classes/Slider.html">Slider</a></li>
            
                <li><a href="../classes/Spinner.html">Spinner</a></li>
            
                <li><a href="../classes/Tab.html">Tab</a></li>
            
                <li><a href="../classes/ToolBar.html">ToolBar</a></li>
            
                <li><a href="../classes/Tooltip.html">Tooltip</a></li>
            
                <li><a href="../classes/Tree.html">Tree</a></li>
            
                <li><a href="../classes/Wizard.html">Wizard</a></li>
            
            </ul>

            <ul id="api-modules" class="apis modules">
            
            </ul>
        </div>
    </div>
</div>

            </div>
        </div>
        <div class="yui3-u-3-4">
                <div id="api-options">
        Show:
        <label for="api-show-inherited">
            <input type="checkbox" id="api-show-inherited" checked>
            Inherited
        </label>

        <label for="api-show-protected">
            <input type="checkbox" id="api-show-protected">
            Protected
        </label>

        <label for="api-show-private">
            <input type="checkbox" id="api-show-private">
            Private
        </label>
        <label for="api-show-deprecated">
            <input type="checkbox" id="api-show-deprecated">
            Deprecated
        </label>

    </div>


            <div class="apidocs">
                <div id="docs-main">
                    <div class="content">
                        <h1 class="file-heading">File: /home/zjh/git/Koala-UI/KoalaUI/WebContent/lib/Koala_Calendar.js</h1>

<div class="file">
    <pre class="code prettyprint linenums">
/**
 * 日历组件，暂不包括农历
 * @param $
 */
(function($) {
	&quot;use strict&quot;;

	Date.prototype.getWeek = function() {
		var onejan = new Date(this.getFullYear(), 0, 1);
		return Math.ceil((((this.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7);
	};
	Date.prototype.getMonthFormatted = function() {
		var month = this.getMonth() + 1;
		return month &lt; 10 ? &#x27;0&#x27; + month : month;
	};
	Date.prototype.getDateFormatted = function() {
		var date = this.getDate();
		return date &lt; 10 ? &#x27;0&#x27; + date : date;
	};
	if(!String.prototype.format) {
		String.prototype.format = function() {
			var args = arguments;
			return this.replace(/{(\d+)}/g, function(match, number) {
				return typeof args[number] != &#x27;undefined&#x27; ? args[number] : match;
			});
		};
	}
	if(!String.prototype.formatNum) {
		String.prototype.formatNum = function(decimal) {
			var r = &quot;&quot; + this;
			while(r.length &lt; decimal)
				r = &quot;0&quot; + r;
			return r;
		};
	}
	
	var defaults = {
		// Width of the calendar
		width:              &#x27;100%&#x27;,
		// Initial view (can be &#x27;month&#x27;, &#x27;week&#x27;, &#x27;day&#x27;)
		view:               &#x27;month&#x27;,
		// Initial date. No matter month, week or day this will be a starting point. Can be &#x27;now&#x27; or a date in format &#x27;yyyy-mm-dd&#x27;
		day:                &#x27;now&#x27;,
		// Day Start time and end time with time intervals. Time split 10, 15 or 30.
		time_start:         &#x27;06:00&#x27;,
		time_end:           &#x27;22:00&#x27;,
		time_split:         &#x27;30&#x27;,
		// Source of events data. It can be one of the following:
		// - URL to return JSON list of events in special format.
		//   {success:1, result: [....]} or for error {success:0, error:&#x27;Something terrible happened&#x27;}
		//   events: [...] as described in events property description
		//   The start and end variables will be sent to this url
		// - A function that received the start and end date, and that
		//   returns an array of events (as described in events property description)
		// - An array containing the events
		events_source:      &#x27;&#x27;,
		// Path to templates should end with slash /. It can be as relative
		// /component/bootstrap-calendar/tmpls/
		// or absolute
		// http://localhost/component/bootstrap-calendar/tmpls/
		tmpl_path:          &#x27;tmpls/&#x27;,
		tmpl_cache:         true,
		classes:            {
			months: {
				inmonth:  &#x27;cal-day-inmonth&#x27;,
				outmonth: &#x27;cal-day-outmonth&#x27;,
				saturday: &#x27;cal-day-weekend&#x27;,
				sunday:   &#x27;cal-day-weekend&#x27;,
				holidays: &#x27;cal-day-holiday&#x27;,
				today:    &#x27;cal-day-today&#x27;
			},
			week:   {
				workday:  &#x27;cal-day-workday&#x27;,
				saturday: &#x27;cal-day-weekend&#x27;,
				sunday:   &#x27;cal-day-weekend&#x27;,
				holidays: &#x27;cal-day-holiday&#x27;,
				today:    &#x27;cal-day-today&#x27;
			}
		},
		// ID of the element of modal window. If set, events URLs will be opened in modal windows.
		modal:              null,
		//	modal handling setting, one of &quot;iframe&quot;, &quot;ajax&quot; or &quot;template&quot;
		modal_type:         &quot;iframe&quot;,
		//	function to set modal title, will be passed the event as a parameter
		modal_title:        null,
		views:              {
			year:  {
				slide_events: 1,
				enable:       1
			},
			month: {
				slide_events: 1,
				enable:       1
			},
			week:  {
				enable: 1
			},
			day:   {
				enable: 1
			}
		},
		merge_holidays:     false,
		// ------------------------------------------------------------
		// CALLBACKS. Events triggered by calendar class. You can use
		// those to affect you UI
		// ------------------------------------------------------------
		onAfterEventsLoad:  function(events) {
			// Inside this function &#x27;this&#x27; is the calendar instance
		},
		onBeforeEventsLoad: function(next) {
			// Inside this function &#x27;this&#x27; is the calendar instance
			next();
		},
		onAfterViewLoad:    function(view) {
			// Inside this function &#x27;this&#x27; is the calendar instance
		},
		// -------------------------------------------------------------
		// INTERNAL USE ONLY. DO NOT ASSIGN IT WILL BE OVERRIDDEN ANYWAY
		// -------------------------------------------------------------
		events:             [],
		templates:          {
			year:  &#x27;&#x27;,
			month: &#x27;&#x27;,
			week:  &#x27;&#x27;,
			day:   &#x27;&#x27;
		},
		stop_cycling:       false
	};

	var defaults_extended = {
		first_day: 2,
		holidays:  {
			// January 1
			&#x27;01-01&#x27;:  &quot;New Year&#x27;s Day&quot;,
			// Third (+3*) Monday (1) in January (01)
			&#x27;01+3*1&#x27;: &quot;Birthday of Dr. Martin Luther King, Jr.&quot;,
			// Third (+3*) Monday (1) in February (02)
			&#x27;02+3*1&#x27;: &quot;Washington&#x27;s Birthday&quot;,
			// Last (-1*) Monday (1) in May (05)
			&#x27;05-1*1&#x27;: &quot;Memorial Day&quot;,
			// July 4
			&#x27;04-07&#x27;:  &quot;Independence Day&quot;,
			// First (+1*) Monday (1) in September (09)
			&#x27;09+1*1&#x27;: &quot;Labor Day&quot;,
			// Second (+2*) Monday (1) in October (10)
			&#x27;10+2*1&#x27;: &quot;Columbus Day&quot;,
			// November 11
			&#x27;11-11&#x27;:  &quot;Veterans Day&quot;,
			// Fourth (+4*) Thursday (4) in November (11)
			&#x27;11+4*4&#x27;: &quot;Thanksgiving Day&quot;,
			// December 25
			&#x27;25-12&#x27;:  &quot;Christmas&quot;
		}
	};

	var strings = {
		error_noview:     &#x27;Calendar: View {0} not found&#x27;,
		error_dateformat: &#x27;Calendar: Wrong date format {0}. Should be either &quot;now&quot; or &quot;yyyy-mm-dd&quot;&#x27;,
		error_loadurl:    &#x27;Calendar: Event URL is not set&#x27;,
		error_where:      &#x27;Calendar: Wrong navigation direction {0}. Can be only &quot;next&quot; or &quot;prev&quot; or &quot;today&quot;&#x27;,
		error_timedevide: &#x27;Calendar: Time split parameter should divide 60 without decimals. Something like 10, 15, 30&#x27;,

		no_events_in_day: &#x27;No events in this day.&#x27;,

		title_year:  &#x27;{0}&#x27;,
		title_month: &#x27;{0} {1}&#x27;,
		title_week:  &#x27;week {0} of {1}&#x27;,
		title_day:   &#x27;{0} {1} {2}, {3}&#x27;,

		week:        &#x27;Week {0}&#x27;,
		all_day:     &#x27;All day&#x27;,
		time:        &#x27;Time&#x27;,
		events:      &#x27;Events&#x27;,
		before_time: &#x27;Ends before timeline&#x27;,
		after_time:  &#x27;Starts after timeline&#x27;,


		m0:  &#x27;January&#x27;,
		m1:  &#x27;February&#x27;,
		m2:  &#x27;March&#x27;,
		m3:  &#x27;April&#x27;,
		m4:  &#x27;May&#x27;,
		m5:  &#x27;June&#x27;,
		m6:  &#x27;July&#x27;,
		m7:  &#x27;August&#x27;,
		m8:  &#x27;September&#x27;,
		m9:  &#x27;October&#x27;,
		m10: &#x27;November&#x27;,
		m11: &#x27;December&#x27;,

		ms0:  &#x27;Jan&#x27;,
		ms1:  &#x27;Feb&#x27;,
		ms2:  &#x27;Mar&#x27;,
		ms3:  &#x27;Apr&#x27;,
		ms4:  &#x27;May&#x27;,
		ms5:  &#x27;Jun&#x27;,
		ms6:  &#x27;Jul&#x27;,
		ms7:  &#x27;Aug&#x27;,
		ms8:  &#x27;Sep&#x27;,
		ms9:  &#x27;Oct&#x27;,
		ms10: &#x27;Nov&#x27;,
		ms11: &#x27;Dec&#x27;,

		d0: &#x27;Sunday&#x27;,
		d1: &#x27;Monday&#x27;,
		d2: &#x27;Tuesday&#x27;,
		d3: &#x27;Wednesday&#x27;,
		d4: &#x27;Thursday&#x27;,
		d5: &#x27;Friday&#x27;,
		d6: &#x27;Saturday&#x27;
	};

	var browser_timezone = &#x27;&#x27;;
	try {
		if($.type(window.jstz) == &#x27;object&#x27; &amp;&amp; $.type(jstz.determine) == &#x27;function&#x27;) {
			browser_timezone = jstz.determine().name();
			if($.type(browser_timezone) !== &#x27;string&#x27;) {
				browser_timezone = &#x27;&#x27;;
			}
		}
	}
	catch(e) {
	}

	function buildEventsUrl(events_url, data) {
		var separator, key, url;
		url = events_url;
		separator = (events_url.indexOf(&#x27;?&#x27;) &lt; 0) ? &#x27;?&#x27; : &#x27;&amp;&#x27;;
		for(key in data) {
			url += separator + key + &#x27;=&#x27; + encodeURIComponent(data[key]);
			separator = &#x27;&amp;&#x27;;
		}
		return url;
	}

	function getExtentedOption(cal, option_name) {
		var fromOptions = (cal.options[option_name] != null) ? cal.options[option_name] : null;
		var fromLanguage = (cal.locale[option_name] != null) ? cal.locale[option_name] : null;
		if((option_name == &#x27;holidays&#x27;) &amp;&amp; cal.options.merge_holidays) {
			var holidays = {};
			$.extend(true, holidays, fromLanguage ? fromLanguage : defaults_extended.holidays);
			if(fromOptions) {
				$.extend(true, holidays, fromOptions);
			}
			return holidays;
		}
		else {
			if(fromOptions != null) {
				return fromOptions;
			}
			if(fromLanguage != null) {
				return fromLanguage;
			}
			return defaults_extended[option_name];
		}
	}

	function getHolidays(cal, year) {
		var hash = [];
		var holidays_def = getExtentedOption(cal, &#x27;holidays&#x27;);
		for(var k in holidays_def) {
			hash.push(k + &#x27;:&#x27; + holidays_def[k]);
		}
		hash.push(year);
		hash = hash.join(&#x27;|&#x27;);
		if(hash in getHolidays.cache) {
			return getHolidays.cache[hash];
		}
		var holidays = [];
		$.each(holidays_def, function(key, name) {
			var firstDay = null, lastDay = null, failed = false;
			$.each(key.split(&#x27;&gt;&#x27;), function(i, chunk) {
				var m, date = null;
				if(m = /^(\d\d)-(\d\d)$/.exec(chunk)) {
					date = new Date(year, parseInt(m[2], 10) - 1, parseInt(m[1], 10));
				}
				else if(m = /^(\d\d)-(\d\d)-(\d\d\d\d)$/.exec(chunk)) {
					if(parseInt(m[3], 10) == year) {
						date = new Date(year, parseInt(m[2], 10) - 1, parseInt(m[1], 10));
					}
				}
				else if(m = /^easter(([+\-])(\d+))?$/.exec(chunk)) {
					date = getEasterDate(year, m[1] ? parseInt(m[1], 10) : 0);
				}
				else if(m = /^(\d\d)([+\-])([1-5])\*([0-6])$/.exec(chunk)) {
					var month = parseInt(m[1], 10) - 1;
					var direction = m[2];
					var offset = parseInt(m[3]);
					var weekday = parseInt(m[4]);
					switch(direction) {
						case &#x27;+&#x27;:
							var d = new Date(year, month, 1 - 7);
							while(d.getDay() != weekday) {
								d = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1);
							}
							date = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 7 * offset);
							break;
						case &#x27;-&#x27;:
							var d = new Date(year, month + 1, 0 + 7);
							while(d.getDay() != weekday) {
								d = new Date(d.getFullYear(), d.getMonth(), d.getDate() - 1);
							}
							date = new Date(d.getFullYear(), d.getMonth(), d.getDate() - 7 * offset);
							break;
					}
				}
				if(!date) {
					warn(&#x27;Unknown holiday: &#x27; + key);
					failed = true;
					return false;
				}
				switch(i) {
					case 0:
						firstDay = date;
						break;
					case 1:
						if(date.getTime() &lt;= firstDay.getTime()) {
							warn(&#x27;Unknown holiday: &#x27; + key);
							failed = true;
							return false;
						}
						lastDay = date;
						break;
					default:
						warn(&#x27;Unknown holiday: &#x27; + key);
						failed = true;
						return false;
				}
			});
			if(!failed) {
				var days = [];
				if(lastDay) {
					for(var date = new Date(firstDay.getTime()); date.getTime() &lt;= lastDay.getTime(); date.setDate(date.getDate() + 1)) {
						days.push(new Date(date.getTime()));
					}
				}
				else {
					days.push(firstDay);
				}
				holidays.push({name: name, days: days});
			}
		});
		getHolidays.cache[hash] = holidays;
		return getHolidays.cache[hash];
	}

	getHolidays.cache = {};

	function warn(message) {
		if($.type(window.console) == &#x27;object&#x27; &amp;&amp; $.type(window.console.warn) == &#x27;function&#x27;) {
			window.console.warn(&#x27;[Bootstrap-Calendar] &#x27; + message);
		}
	}

	function Calendar(params, context) {
		this.options = $.extend(true, {position: {start: new Date(), end: new Date()}}, defaults, params);
		this.setLanguage(this.options.language);
		this.context = context;

		context.css(&#x27;width&#x27;, this.options.width).addClass(&#x27;cal-context&#x27;);

		this.view();
		return this;
	}

	Calendar.prototype.setOptions = function(object) {
		$.extend(this.options, object);
		if(&#x27;language&#x27; in object) {
			this.setLanguage(object.language);
		}
		if(&#x27;modal&#x27; in object) {
			this._update_modal();
		}
	}

	Calendar.prototype.setLanguage = function(lang) {
		if(window.calendar_languages &amp;&amp; (lang in window.calendar_languages)) {
			this.locale = $.extend(true, {}, strings, calendar_languages[lang]);
			this.options.language = lang;
		} else {
			this.locale = strings;
			delete this.options.language;
		}
	}

	Calendar.prototype._render = function() {
		this.context.html(&#x27;&#x27;);
		this._loadTemplate(this.options.view);
		this.stop_cycling = false;

		var data = {};
		data.cal = this;
		data.day = 1;

		// Getting list of days in a week in correct order. Works for month and week views
		if(getExtentedOption(this, &#x27;first_day&#x27;) == 1) {
			data.months = [this.locale.d1, this.locale.d2, this.locale.d3, this.locale.d4, this.locale.d5, this.locale.d6, this.locale.d0]
		} else {
			data.months = [this.locale.d0, this.locale.d1, this.locale.d2, this.locale.d3, this.locale.d4, this.locale.d5, this.locale.d6]
		}

		// Get all events between start and end
		var start = parseInt(this.options.position.start.getTime());
		var end = parseInt(this.options.position.end.getTime());

		data.events = this.getEventsBetween(start, end);

		switch(this.options.view) {
			case &#x27;month&#x27;:
				break;
			case &#x27;week&#x27;:
				this._calculate_hour_minutes(data);
				break;
			case &#x27;day&#x27;:
				this._calculate_hour_minutes(data);
				break;
		}

		data.start = new Date(this.options.position.start.getTime());
		data.lang = this.locale;

		this.context.append(this.options.templates[this.options.view](data));
		this._update();
	};

	Calendar.prototype._calculate_hour_minutes = function(data) {
		var $self = this;
		data.in_hour = 60 / parseInt(this.options.time_split);
		data.hour_split = parseInt(this.options.time_split);

		if(!/^\d+$/.exec(data.in_hour) || this.options.time_split &gt; 30) {
			$.error(this.locale.error_timedevide);
		}

		var time_start = this.options.time_start.split(&quot;:&quot;);
		var time_end = this.options.time_end.split(&quot;:&quot;);

		data.hours = (parseInt(time_end[0]) - parseInt(time_start[0]));
		var lines = data.hours * data.in_hour;
		var ms_per_line = (60000 * parseInt(this.options.time_split));

		var start = new Date(this.options.position.start.getTime());
		start.setHours(time_start[0]);
		start.setMinutes(time_start[1]);
		var end = new Date(this.options.position.start.getTime());
		end.setHours(time_end[0]);
		end.setMinutes(time_end[1]);

		data.all_day = [];
		data.by_hour = [];
		data.after_time = [];
		data.before_time = [];
		$.each(data.events, function(k, e) {
			var s = new Date(parseInt(e.start));
			var f = new Date(parseInt(e.end));

			e.start_hour = s.getHours().toString().formatNum(2) + &#x27;:&#x27; + s.getMinutes().toString().formatNum(2);
			e.end_hour = f.getHours().toString().formatNum(2) + &#x27;:&#x27; + f.getMinutes().toString().formatNum(2);

			if(e.start &lt; start.getTime()) {
				warn(1);
				e.start_hour = s.getDate() + &#x27; &#x27; + $self.locale[&#x27;ms&#x27; + s.getMonth()] + &#x27; &#x27; + e.start_hour;
			}

			if(e.end &gt; end.getTime()) {
				warn(1);
				e.end_hour = f.getDate() + &#x27; &#x27; + $self.locale[&#x27;ms&#x27; + f.getMonth()] + &#x27; &#x27; + e.end_hour;
			}

			if(e.start &lt; start.getTime() &amp;&amp; e.end &gt; end.getTime()) {
				data.all_day.push(e);
				return;
			}

			if(e.end &lt; start.getTime()) {
				data.before_time.push(e);
				return;
			}

			if(e.start &gt; end.getTime()) {
				data.after_time.push(e);
				return;
			}

			var event_start = start.getTime() - e.start;

			if(event_start &gt;= 0) {
				e.top = 0;
			} else {
				e.top = Math.abs(event_start) / ms_per_line;
			}

			var lines_left = lines - e.top;
			var lines_in_event = (e.end - e.start) / ms_per_line;
			if(event_start &gt;= 0) {
				lines_in_event = (e.end - start.getTime()) / ms_per_line;
			}


			e.lines = lines_in_event;
			if(lines_in_event &gt; lines_left) {
				e.lines = lines_left;
			}

			data.by_hour.push(e);
		});

		//var d = new Date(&#x27;2013-03-14 13:20:00&#x27;);
		//warn(d.getTime());
	};

	Calendar.prototype._hour = function(hour, part) {
		var time_start = this.options.time_start.split(&quot;:&quot;);

		var hour = &quot;&quot; + (parseInt(time_start[0]) + hour);
		var minute = &quot;&quot; + (this.options.time_split * part);

		return hour.formatNum(2) + &quot;:&quot; + minute.formatNum(2);
	}

	Calendar.prototype._week = function(event) {
		this._loadTemplate(&#x27;week-days&#x27;);

		var t = {};
		var start = parseInt(this.options.position.start.getTime());
		var end = parseInt(this.options.position.end.getTime());
		var events = [];
		var self = this;
		var first_day = getExtentedOption(this, &#x27;first_day&#x27;);

		$.each(this.getEventsBetween(start, end), function(k, event) {
			event.start_day = new Date(parseInt(event.start)).getDay();
			if(first_day == 1) {
				event.start_day = (event.start_day + 6) % 7;
			}
			if((event.end - event.start) &lt;= 86400000) {
				event.days = 1;
			} else {
				event.days = ((event.end - event.start) / 86400000);
			}

			if(event.start &lt; start) {

				event.days = event.days - ((start - event.start) / 86400000);
				event.start_day = 0;
			}

			event.days = Math.ceil(event.days);

			if(event.start_day + event.days &gt; 7) {
				event.days = 7 - (event.start_day);
			}

			events.push(event);
		});
		t.events = events;
		t.cal = this;
		return self.options.templates[&#x27;week-days&#x27;](t);
	}

	Calendar.prototype._month = function(month) {
		this._loadTemplate(&#x27;year-month&#x27;);

		var t = {cal: this};
		var newmonth = month + 1;
		t.data_day = this.options.position.start.getFullYear() + &#x27;-&#x27; + (newmonth &lt; 10 ? &#x27;0&#x27; + newmonth : newmonth) + &#x27;-&#x27; + &#x27;01&#x27;;
		t.month_name = this.locale[&#x27;m&#x27; + month];

		var curdate = new Date(this.options.position.start.getFullYear(), month, 1, 0, 0, 0);
		t.start = parseInt(curdate.getTime());
		t.end = parseInt(new Date(this.options.position.start.getFullYear(), month + 1, 1, 0, 0, 0).getTime());
		t.events = this.getEventsBetween(t.start, t.end);
		return this.options.templates[&#x27;year-month&#x27;](t);
	}

	Calendar.prototype._day = function(week, day) {
		this._loadTemplate(&#x27;month-day&#x27;);

		var t = {tooltip: &#x27;&#x27;, cal: this};
		var cls = this.options.classes.months.outmonth;

		var firstday = this.options.position.start.getDay();
		if(getExtentedOption(this, &#x27;first_day&#x27;) == 2) {
			firstday++;
		} else {
			firstday = (firstday == 0 ? 7 : firstday);
		}

		day = (day - firstday) + 1;
		var curdate = new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), day, 0, 0, 0);

		// if day of the current month
		if(day &gt; 0) {
			cls = this.options.classes.months.inmonth;
		}
		// stop cycling table rows;
		var daysinmonth = (new Date(this.options.position.end.getTime() - 1)).getDate();
		if((day + 1) &gt; daysinmonth) {
			this.stop_cycling = true;
		}
		// if day of the next month
		if(day &gt; daysinmonth) {
			day = day - daysinmonth;
			cls = this.options.classes.months.outmonth;
		}

		cls = $.trim(cls + &quot; &quot; + this._getDayClass(&quot;months&quot;, curdate));

		if(day &lt;= 0) {
			var daysinprevmonth = (new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), 0)).getDate();
			day = daysinprevmonth - Math.abs(day);
			cls += &#x27; cal-month-first-row&#x27;;
		}

		var holiday = this._getHoliday(curdate);
		if(holiday !== false) {
			t.tooltip = holiday;
		}

		t.data_day = curdate.getFullYear() + &#x27;-&#x27; + curdate.getMonthFormatted() + &#x27;-&#x27; + (day &lt; 10 ? &#x27;0&#x27; + day : day);
		t.cls = cls;
		t.day = day;

		t.start = parseInt(curdate.getTime());
		t.end = parseInt(t.start + 86400000);
		t.events = this.getEventsBetween(t.start, t.end);
		return this.options.templates[&#x27;month-day&#x27;](t);
	}

	Calendar.prototype._getHoliday = function(date) {
		var result = false;
		$.each(getHolidays(this, date.getFullYear()), function() {
			var found = false;
			$.each(this.days, function() {
				if(this.toDateString() == date.toDateString()) {
					found = true;
					return false;
				}
			});
			if(found) {
				result = this.name;
				return false;
			}
		});
		return result;
	};

	Calendar.prototype._getHolidayName = function(date) {
		var holiday = this._getHoliday(date);
		return (holiday === false) ? &quot;&quot; : holiday;
	};

	Calendar.prototype._getDayClass = function(class_group, date) {
		var self = this;
		var addClass = function(which, to) {
			var cls;
			cls = (self.options.classes &amp;&amp; (class_group in self.options.classes) &amp;&amp; (which in self.options.classes[class_group])) ? self.options.classes[class_group][which] : &quot;&quot;;
			if((typeof(cls) == &quot;string&quot;) &amp;&amp; cls.length) {
				to.push(cls);
			}
		};
		var classes = [];
		if(date.toDateString() == (new Date()).toDateString()) {
			addClass(&quot;today&quot;, classes);
		}
		var holiday = this._getHoliday(date);
		if(holiday !== false) {
			addClass(&quot;holidays&quot;, classes);
		}
		switch(date.getDay()) {
			case 0:
				addClass(&quot;sunday&quot;, classes);
				break;
			case 6:
				addClass(&quot;saturday&quot;, classes);
				break;
		}
		
		addClass(date.toDateString(), classes);

		return classes.join(&quot; &quot;);
	};

	Calendar.prototype.view = function(view) {
		if(view) {
			if(!this.options.views[view].enable) {
				return;
			}
			this.options.view = view;
		}


		this._init_position();
		this._loadEvents();
		this._render();

		this.options.onAfterViewLoad.call(this, this.options.view);
	};

	Calendar.prototype.navigate = function(where, next) {
		var to = $.extend({}, this.options.position);
		if(where == &#x27;next&#x27;) {
			switch(this.options.view) {
				case &#x27;year&#x27;:
					to.start.setFullYear(this.options.position.start.getFullYear() + 1);
					break;
				case &#x27;month&#x27;:
					to.start.setMonth(this.options.position.start.getMonth() + 1);
					break;
				case &#x27;week&#x27;:
					to.start.setDate(this.options.position.start.getDate() + 7);
					break;
				case &#x27;day&#x27;:
					to.start.setDate(this.options.position.start.getDate() + 1);
					break;
			}
		} else if(where == &#x27;prev&#x27;) {
			switch(this.options.view) {
				case &#x27;year&#x27;:
					to.start.setFullYear(this.options.position.start.getFullYear() - 1);
					break;
				case &#x27;month&#x27;:
					to.start.setMonth(this.options.position.start.getMonth() - 1);
					break;
				case &#x27;week&#x27;:
					to.start.setDate(this.options.position.start.getDate() - 7);
					break;
				case &#x27;day&#x27;:
					to.start.setDate(this.options.position.start.getDate() - 1);
					break;
			}
		} else if(where == &#x27;today&#x27;) {
			to.start.setTime(new Date().getTime());
		}
		else {
			$.error(this.locale.error_where.format(where))
		}
		this.options.day = to.start.getFullYear() + &#x27;-&#x27; + to.start.getMonthFormatted() + &#x27;-&#x27; + to.start.getDateFormatted();
		this.view();
		if(_.isFunction(next)) {
			next();
		}
	};

	Calendar.prototype._init_position = function() {
		var year, month, day;

		if(this.options.day == &#x27;now&#x27;) {
			var date = new Date();
			year = date.getFullYear();
			month = date.getMonth();
			day = date.getDate();
		} else if(this.options.day.match(/^\d{4}-\d{2}-\d{2}$/g)) {
			var list = this.options.day.split(&#x27;-&#x27;);
			year = parseInt(list[0], 10);
			month = parseInt(list[1], 10) - 1;
			day = parseInt(list[2], 10);
		}
		else {
			$.error(this.locale.error_dateformat.format(this.options.day));
		}

		switch(this.options.view) {
			case &#x27;year&#x27;:
				this.options.position.start.setTime(new Date(year, 0, 1).getTime());
				this.options.position.end.setTime(new Date(year + 1, 0, 1).getTime());
				break;
			case &#x27;month&#x27;:
				this.options.position.start.setTime(new Date(year, month, 1).getTime());
				this.options.position.end.setTime(new Date(year, month + 1, 1).getTime());
				break;
			case &#x27;day&#x27;:
				this.options.position.start.setTime(new Date(year, month, day).getTime());
				this.options.position.end.setTime(new Date(year, month, day + 1).getTime());
				break;
			case &#x27;week&#x27;:
				var curr = new Date(year, month, day);
				var first;
				if(getExtentedOption(this, &#x27;first_day&#x27;) == 1) {
					first = curr.getDate() - ((curr.getDay() + 6) % 7);
				}
				else {
					first = curr.getDate() - curr.getDay();
				}
				this.options.position.start.setTime(new Date(year, month, first).getTime());
				this.options.position.end.setTime(new Date(year, month, first + 7).getTime());
				break;
			default:
				$.error(this.locale.error_noview.format(this.options.view))
		}
		return this;
	};

	Calendar.prototype.getTitle = function() {
		var p = this.options.position.start;
		switch(this.options.view) {
			case &#x27;year&#x27;:
				return this.locale.title_year.format(p.getFullYear());
				break;
			case &#x27;month&#x27;:
				return this.locale.title_month.format(this.locale[&#x27;m&#x27; + p.getMonth()], p.getFullYear());
				break;
			case &#x27;week&#x27;:
				return this.locale.title_week.format(p.getWeek(), p.getFullYear());
				break;
			case &#x27;day&#x27;:
				return this.locale.title_day.format(this.locale[&#x27;d&#x27; + p.getDay()], p.getDate(), this.locale[&#x27;m&#x27; + p.getMonth()], p.getFullYear());
				break;
		}
		return;
	};

	Calendar.prototype.isToday = function() {
		var now = new Date().getTime();

		return ((now &gt; this.options.position.start) &amp;&amp; (now &lt; this.options.position.end));
	}

	Calendar.prototype.getStartDate = function() {
		return this.options.position.start;
	}

	Calendar.prototype.getEndDate = function() {
		return this.options.position.end;
	}

	Calendar.prototype._loadEvents = function() {
		var self = this;
		var source = null;
		if(&#x27;events_source&#x27; in this.options &amp;&amp; this.options.events_source !== &#x27;&#x27;) {
			source = this.options.events_source;
		}
		else if(&#x27;events_url&#x27; in this.options) {
			source = this.options.events_url;
			warn(&#x27;The events_url option is DEPRECATED and it will be REMOVED in near future. Please use events_source instead.&#x27;);
		}
		var loader;
		switch($.type(source)) {
			case &#x27;function&#x27;:
				loader = function() {
					return source(self.options.position.start, self.options.position.end, browser_timezone);
				};
				break;
			case &#x27;array&#x27;:
				loader = function() {
					return [].concat(source);
				};
				break;
			case &#x27;string&#x27;:
				if(source.length) {
					loader = function() {
						var events = [];
						var params = {from: self.options.position.start.getTime(), to: self.options.position.end.getTime()};
						if(browser_timezone.length) {
							params.browser_timezone = browser_timezone;
						}
						$.ajax({
							url:      buildEventsUrl(source, params),
							dataType: &#x27;json&#x27;,
							type:     &#x27;GET&#x27;,
							async:    false
						}).done(function(json) {
								if(!json.success) {
									$.error(json.error);
								}
								if(json.result) {
									events = json.result;
								}
							});
						return events;
					};
				}
				break;
		}
		if(!loader) {
			$.error(this.locale.error_loadurl);
		}
		this.options.onBeforeEventsLoad.call(this, function() {
			self.options.events = loader();
			self.options.events.sort(function(a, b) {
				var delta;
				delta = a.start - b.start;
				if(delta == 0) {
					delta = a.end - b.end;
				}
				return delta;
			});
			self.options.onAfterEventsLoad.call(self, self.options.events);
		});
	};

	Calendar.prototype._loadTemplate = function(name) {
		if(this.options.templates[name]) {
			return;
		}
		var self = this;
		$.ajax({
			url:      this.options.tmpl_path + name + &#x27;.html&#x27;,
			dataType: &#x27;html&#x27;,
			type:     &#x27;GET&#x27;,
			async:    false,
			cache:    this.options.tmpl_cache
		}).done(function(html) {
				self.options.templates[name] = _.template(html);
			});
	};


	Calendar.prototype._update = function() {
		var self = this;

		$(&#x27;*[data-toggle=&quot;tooltip&quot;]&#x27;).tooltip({container: &#x27;body&#x27;});

		$(&#x27;*[data-cal-date]&#x27;).click(function() {
			var view = $(this).data(&#x27;cal-view&#x27;);
			self.options.day = $(this).data(&#x27;cal-date&#x27;);
			self.view(view);
		});
		$(&#x27;.cal-cell&#x27;).dblclick(function() {
			var view = $(&#x27;[data-cal-date]&#x27;, this).data(&#x27;cal-view&#x27;);
			self.options.day = $(&#x27;[data-cal-date]&#x27;, this).data(&#x27;cal-date&#x27;);
			self.view(view);
		});

		this[&#x27;_update_&#x27; + this.options.view]();

		this._update_modal();

	};

	Calendar.prototype._update_modal = function() {
		var self = this;

		$(&#x27;a[data-event-id]&#x27;, this.context).unbind(&#x27;click&#x27;);

		if(!self.options.modal) {
			return;
		}

		var modal = $(self.options.modal);

		if(!modal.length) {
			return;
		}

		var ifrm = null;
		if(self.options.modal_type == &quot;iframe&quot;) {
			ifrm = $(document.createElement(&quot;iframe&quot;))
				.attr({
					width:       &quot;100%&quot;,
					frameborder: &quot;0&quot;
				});
		}


		$(&#x27;a[data-event-id]&#x27;, this.context).on(&#x27;click&#x27;, function(event) {
			event.preventDefault();
			event.stopPropagation();

			var url = $(this).attr(&#x27;href&#x27;);
			var id = $(this).data(&quot;event-id&quot;);
			var event = _.find(self.options.events, function(event) {
				return event.id == id
			});

			if(self.options.modal_type == &quot;iframe&quot;) {
				ifrm.attr(&#x27;src&#x27;, url);
				$(&#x27;.modal-body&#x27;, modal).html(ifrm);
			}

			if(!modal.data(&#x27;handled.bootstrap-calendar&#x27;) || (modal.data(&#x27;handled.bootstrap-calendar&#x27;) &amp;&amp; modal.data(&#x27;handled.event-id&#x27;) != event.id)) {
				modal
					.on(&#x27;show.bs.modal&#x27;, function() {
						var modal_body = $(this).find(&#x27;.modal-body&#x27;);
						switch(self.options.modal_type) {
							case &quot;iframe&quot; :
								var height = modal_body.height() - parseInt(modal_body.css(&#x27;padding-top&#x27;), 10) - parseInt(modal_body.css(&#x27;padding-bottom&#x27;), 10);
								$(this).find(&#x27;iframe&#x27;).height(Math.max(height, 50));
								break;

							case &quot;ajax&quot;:
								$.ajax({url: url, dataType: &quot;html&quot;, async: false, success: function(data) {
									modal_body.html(data);
								}});
								break;

							case &quot;template&quot;:
								self._loadTemplate(&quot;modal&quot;);
								//	also serve calendar instance to underscore template to be able to access current language strings
								modal_body.html(self.options.templates[&quot;modal&quot;]({&quot;event&quot;: event, &quot;calendar&quot;: self}))
								break;
						}

						//	set the title of the bootstrap modal
						if(_.isFunction(self.options.modal_title)) {
							modal.find(&quot;h3&quot;).html(self.options.modal_title(event));
						}
					})
					.data(&#x27;handled.bootstrap-calendar&#x27;, true).data(&#x27;handled.event-id&#x27;, event.id);
			}
			modal.modal(&#x27;show&#x27;);
		});
	};

	Calendar.prototype._update_day = function() {
		$(&#x27;#cal-day-panel&#x27;).height($(&#x27;#cal-day-panel-hour&#x27;).height());
	};

	Calendar.prototype._update_week = function() {
	};

	Calendar.prototype._update_year = function() {
		this._update_month_year();
	};

	Calendar.prototype._update_month = function() {
		this._update_month_year();

		var self = this;

		var week = $(document.createElement(&#x27;div&#x27;)).attr(&#x27;id&#x27;, &#x27;cal-week-box&#x27;);
		var start = this.options.position.start.getFullYear() + &#x27;-&#x27; + this.options.position.start.getMonthFormatted() + &#x27;-&#x27;;
		$(&#x27;.cal-month-box .cal-row-fluid&#x27;)
			.on(&#x27;mouseenter&#x27;, function() {
				var p = new Date(self.options.position.start);
				var child = $(&#x27;.cal-cell1:first-child .cal-month-day&#x27;, this);
				var day = (child.hasClass(&#x27;cal-month-first-row&#x27;) ? 1 : $(&#x27;[data-cal-date]&#x27;, child).text());
				p.setDate(parseInt(day));
				day = (day &lt; 10 ? &#x27;0&#x27; + day : day);
				week.html(self.locale.week.format(p.getWeek()));
				week.attr(&#x27;data-cal-week&#x27;, start + day).show().appendTo(child);
			})
			.on(&#x27;mouseleave&#x27;, function() {
				week.hide();
			})
		;

		week.click(function() {
			self.options.day = $(this).data(&#x27;cal-week&#x27;);
			self.view(&#x27;week&#x27;);
		});

		$(&#x27;a.event&#x27;).mouseenter(function() {
			$(&#x27;a[data-event-id=&quot;&#x27; + $(this).data(&#x27;event-id&#x27;) + &#x27;&quot;]&#x27;).closest(&#x27;.cal-cell1&#x27;).addClass(&#x27;day-highlight dh-&#x27; + $(this).data(&#x27;event-class&#x27;));
		});
		$(&#x27;a.event&#x27;).mouseleave(function() {
			$(&#x27;div.cal-cell1&#x27;).removeClass(&#x27;day-highlight dh-&#x27; + $(this).data(&#x27;event-class&#x27;));
		});
	};

	Calendar.prototype._update_month_year = function() {
		if(!this.options.views[this.options.view].slide_events) {
			return;
		}
		var self = this;
		var activecell = 0;
		var downbox = $(document.createElement(&#x27;div&#x27;)).attr(&#x27;id&#x27;, &#x27;cal-day-tick&#x27;).html(&#x27;&lt;i class=&quot;icon-chevron-down glyphicon glyphicon-chevron-down&quot;&gt;&lt;/i&gt;&#x27;);

		$(&#x27;.cal-month-day, .cal-year-box .span3&#x27;)
			.on(&#x27;mouseenter&#x27;, function() {
				if($(&#x27;.events-list&#x27;, this).length == 0) return;
				if($(this).children(&#x27;[data-cal-date]&#x27;).text() == self.activecell) return;
				downbox.show().appendTo(this);
			})
			.on(&#x27;mouseleave&#x27;, function() {
				downbox.hide();
			})
			.on(&#x27;click&#x27;, function(event) {
				if($(&#x27;.events-list&#x27;, this).length == 0) return;
				if($(this).children(&#x27;[data-cal-date]&#x27;).text() == self.activecell) return;
				showEventsList(event, downbox, slider, self);
			})
		;

		var slider = $(document.createElement(&#x27;div&#x27;)).attr(&#x27;id&#x27;, &#x27;cal-slide-box&#x27;);
		slider.hide().click(function(event) {
			event.stopPropagation();
		});

		this._loadTemplate(&#x27;events-list&#x27;);

		downbox.click(function(event) {
			showEventsList(event, $(this), slider, self);
		});
	};

	Calendar.prototype.getEventsBetween = function(start, end) {
		var events = [];
		$.each(this.options.events, function() {
			if((parseInt(this.start) &lt; end || this.start == null) &amp;&amp; (parseInt(this.end) &gt;= start || this.end == null)) {
				events.push(this);
			}
		});
		return events;
	};

	function showEventsList(event, that, slider, self) {

		event.stopPropagation();

		var that = $(that);
		var cell = that.closest(&#x27;.cal-cell&#x27;);
		var row = cell.closest(&#x27;.cal-before-eventlist&#x27;);
		var tick_position = cell.data(&#x27;cal-row&#x27;);

		that.fadeOut(&#x27;fast&#x27;);

		slider.slideUp(&#x27;fast&#x27;, function() {
			var event_list = $(&#x27;.events-list&#x27;, cell);
			slider.html(self.options.templates[&#x27;events-list&#x27;]({
				cal:    self,
				events: self.getEventsBetween(parseInt(event_list.data(&#x27;cal-start&#x27;)), parseInt(event_list.data(&#x27;cal-end&#x27;)))
			}));
			row.after(slider);
			self.activecell = $(&#x27;[data-cal-date]&#x27;, cell).text();
			$(&#x27;#cal-slide-tick&#x27;).addClass(&#x27;tick&#x27; + tick_position).show();
			slider.slideDown(&#x27;fast&#x27;, function() {
				$(&#x27;body&#x27;).one(&#x27;click&#x27;, function() {
					slider.slideUp(&#x27;fast&#x27;);
					self.activecell = 0;
				});
			});
		});

		$(&#x27;a.event-item&#x27;).mouseenter(function() {
			$(&#x27;a[data-event-id=&quot;&#x27; + $(this).data(&#x27;event-id&#x27;) + &#x27;&quot;]&#x27;).closest(&#x27;.cal-cell1&#x27;).addClass(&#x27;day-highlight dh-&#x27; + $(this).data(&#x27;event-class&#x27;));
		});
		$(&#x27;a.event-item&#x27;).mouseleave(function() {
			$(&#x27;div.cal-cell1&#x27;).removeClass(&#x27;day-highlight dh-&#x27; + $(this).data(&#x27;event-class&#x27;));
		});

		self._update_modal();
	}

	function getEasterDate(year, offsetDays) {
		var a = year % 19;
		var b = Math.floor(year / 100);
		var c = year % 100;
		var d = Math.floor(b / 4);
		var e = b % 4;
		var f = Math.floor((b + 8) / 25);
		var g = Math.floor((b - f + 1) / 3);
		var h = (19 * a + b - d - g + 15) % 30;
		var i = Math.floor(c / 4);
		var k = c % 4;
		var l = (32 + 2 * e + 2 * i - h - k) % 7;
		var m = Math.floor((a + 11 * h + 22 * l) / 451);
		var n0 = (h + l + 7 * m + 114)
		var n = Math.floor(n0 / 31) - 1;
		var p = n0 % 31 + 1;
		return new Date(year, n, p + (offsetDays ? offsetDays : 0), 0, 0, 0);
	}

	$.fn.calendar = function(params) {
		return new Calendar(params, this);
	}
}(jQuery));

    </pre>
</div>

                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="../assets/js/yui-prettify.js"></script>
<script src="../assets/../api.js"></script>
<script src="../assets/js/api-filter.js"></script>
<script src="../assets/js/api-list.js"></script>
<script src="../assets/js/api-search.js"></script>
<script src="../assets/js/apidocs.js"></script>
</body>
</html>
